home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / ARGONET / PD / FILER / X-FILES.ZIP / 057 / !X-Files / c / fs < prev    next >
Text File  |  1997-01-21  |  21KB  |  764 lines

  1. /* fs.c */
  2.  
  3. #include "chunks.h"
  4. #include "debug.h"
  5. #include "swis.h"
  6.  
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stdio.h>
  10.  
  11. /*********************************************************************************/
  12. /*                                                                               */
  13. /*   Support routines                                                            */
  14. /*                                                                               */
  15. /*********************************************************************************/
  16.  
  17. static const char *xFiles_Leaf(const char *pName)
  18. {
  19.    const char *lastDot;
  20.  
  21.    if (lastDot = strrchr(pName, '.'), lastDot)
  22.       return lastDot + 1;
  23.  
  24.    return pName;
  25. }
  26.  
  27. static xFiles_fileInfo *xFiles_FindOpenFile(xFiles_info *pInfo, unsigned cnkNum)
  28. {
  29.    xFiles_fileInfo *pFile;
  30.  
  31.    for (pFile = (xFiles_fileInfo *) pInfo->openList.head; pFile; pFile = (xFiles_fileInfo *) pFile->li.next)
  32.    {
  33.       if (pFile->cnkNum == cnkNum)
  34.          return pFile;
  35.    }
  36.  
  37.    return NULL;
  38. }
  39.  
  40. static _kernel_oserror *xFiles_FindObject(xFiles_info *pInfo, const char *fileName,
  41.                                           xFiles_dirHash *pDirHash, xFiles_dirEntry *pDirEnt,
  42.                                           unsigned *pParent)
  43. {
  44.    _kernel_oserror *err;
  45.    unsigned hashOffset;
  46.    
  47.    if (err = xFiles_parsePath(pInfo, fileName, pParent, &hashOffset, NULL, pDirHash, pDirEnt, FALSE), err)
  48.       return err;
  49.  
  50.    if (hashOffset == 0) return &xFiles_NotFound;
  51.  
  52.    return NULL;
  53. }
  54.  
  55. static _kernel_oserror *xFiles_FindDir(xFiles_info *pInfo, const char *fileName,
  56.                                        xFiles_dirHash *pDirHash, xFiles_dirEntry *pDirEnt)
  57. {
  58.    _kernel_oserror *err;
  59.  
  60.    if (err = xFiles_FindObject(pInfo, fileName, pDirHash, pDirEnt, NULL), err)
  61.       return err;
  62.  
  63.    if ((pDirEnt->attr & xFiles_isDir) == 0)
  64.       return &xFiles_NotADir;
  65.  
  66.    return NULL;
  67. }
  68.  
  69. static _kernel_oserror *xFiles_Rename(xFiles_info *pInfo, const char *from, const char *to)
  70. {
  71.    _kernel_oserror *err;
  72.  
  73.    unsigned toDir, toHashOffset;
  74.    unsigned fromDir, fromHashOffset, fromEntryOffset;
  75.    xFiles_dirEntry fromDirEnt;
  76.    xFiles_dirHash  fromDirHash;
  77.  
  78.    /*TRACE("Rename %s %s\n", from, to);*/
  79.  
  80.    if (err = xFiles_parsePath(pInfo, to, &toDir, &toHashOffset, NULL, NULL, NULL, TRUE), err)
  81.       return err;
  82.  
  83.    if (err = xFiles_parsePath(pInfo, from, &fromDir, &fromHashOffset, &fromEntryOffset, &fromDirHash, &fromDirEnt, FALSE), err)
  84.       return err;
  85.  
  86.    /* Create the new entry */
  87.  
  88.    if (err = xFiles_createDirEntry(pInfo, toDir, &fromDirHash, &fromDirEnt, xFiles_Leaf(to)), err)
  89.       return err;
  90.  
  91.    /* If they are in the same directory the offsets might not be valid anymore, so
  92.     * do another scan of the directory to get the latest info.
  93.     */
  94.  
  95.    if (err = xFiles_dirLookup(pInfo, fromDir, xFiles_Leaf(from),
  96.                               &fromHashOffset, &fromEntryOffset, NULL, NULL), err)
  97.       return err;
  98.  
  99.    if (err = xFiles_deleteDirEntry(pInfo, fromDir, fromHashOffset), err)
  100.       return err;
  101.  
  102.    return NULL;
  103. }
  104.  
  105.  
  106. static _kernel_oserror *xFiles_ReadDirEntries(xFiles_info *pInfo, const char *dirName, void *buffer,
  107.                                               int *pCount, int *pNext, int bufSize, BOOL infoToo)
  108. {
  109.    _kernel_oserror *err;
  110.    xFiles_dirHeader dirHdr;
  111.    xFiles_dirHash   dirHash;
  112.    xFiles_dirEntry  dirEnt;
  113.    unsigned         dirObject;
  114.    unsigned         hashPos;
  115.    int              nFiles;
  116.    char             *bufPtr, *bufLimit;
  117.    int              spaceNeeded;
  118.    BOOL             fakeName;
  119.  
  120.    struct fileInfo
  121.    {
  122.       unsigned load, exec, size, attr, type;
  123.    } *pFileInfo;
  124.  
  125.    if (err = xFiles_FindDir(pInfo, dirName, &dirHash, &dirEnt), err)
  126.       return err;
  127.  
  128.    dirObject = dirHash.node;
  129.  
  130.    if (err = xFiles_getDirHeader(pInfo, dirObject, &dirHdr), err)
  131.       return err;
  132.  
  133.    nFiles   = *pCount;
  134.    *pCount  = 0;
  135.    bufPtr   = (char *) buffer;
  136.    bufLimit = bufPtr + bufSize;
  137.  
  138.    while (nFiles > 0 && *pNext < dirHdr.used)
  139.    {
  140.       hashPos = sizeof(xFiles_dirHeader) + sizeof(xFiles_dirHash) * (*pNext);
  141.       fakeName = FALSE;
  142.  
  143.       if (err = xFiles_readChunk(pInfo, &dirHash, dirObject, hashPos, sizeof(dirHash)), err)
  144.          return err;
  145.  
  146.       if (err = xFiles_readChunk(pInfo, &dirEnt, dirObject, dirHash.entryPos, sizeof(dirEnt)), err)
  147.          return err;
  148.  
  149.       if (dirEnt.nameLen > 256 || dirEnt.nameLen == 0)
  150.       {
  151.          TRACE("Fixing broken name (length = %08x)\n", dirEnt.nameLen);
  152.  
  153.          fakeName = TRUE;
  154.          dirEnt.nameLen = 12;
  155.       }
  156.  
  157.       if (infoToo)
  158.          spaceNeeded = 20 + (dirEnt.nameLen + 4) & ~3;
  159.       else
  160.          spaceNeeded = dirEnt.nameLen + 1;
  161.  
  162.       if (bufPtr + spaceNeeded > bufLimit)
  163.          break;
  164.  
  165.       if (infoToo)
  166.       {
  167.          pFileInfo = (struct fileInfo *) bufPtr;
  168.  
  169.          if (fakeName)
  170.          {
  171.             xFiles_chunk cnk;
  172.  
  173.             if (err = xFiles_getChunkInfo(pInfo, dirHash.node, &cnk), err)
  174.                return err;
  175.  
  176.             dirEnt.load =
  177.             dirEnt.exec = 0xFFFFFFFF;
  178.             dirEnt.size = cnk.size;
  179.             dirEnt.attr = xFiles_meRead | xFiles_meWrite;
  180.          }
  181.  
  182.          pFileInfo->load = dirEnt.load;
  183.          pFileInfo->exec = dirEnt.exec;
  184.          pFileInfo->size = dirEnt.size;
  185.          pFileInfo->attr = dirEnt.attr & 0xFF;
  186.          pFileInfo->type = (dirEnt.attr & xFiles_isDir) ? 2 : 1;
  187.          bufPtr = (char *) (pFileInfo + 1);
  188.       }
  189.  
  190.       if (fakeName)
  191.       {
  192.          memcpy(bufPtr, dirHash.nameStart, 4);
  193.          sprintf(bufPtr + 4, "%08d", dirHash.node);
  194.       }
  195.       else
  196.       {
  197.          if (err = xFiles_readChunk(pInfo, bufPtr, dirObject,
  198.                                     dirHash.entryPos + sizeof(dirEnt), dirEnt.nameLen + 1), err)
  199.             return err;
  200.       }
  201.  
  202.       bufPtr += dirEnt.nameLen + 1;   
  203.  
  204.       if (infoToo)
  205.       {
  206.          while (((int) bufPtr & 3) != 0)
  207.             *bufPtr++ = 0;
  208.       }
  209.  
  210.       (*pCount)++;
  211.       (*pNext)++;
  212.       nFiles--;
  213.    }
  214.  
  215.    if (*pNext >= dirHdr.used)
  216.       *pNext = -1;
  217.  
  218.    return NULL;
  219. }
  220.  
  221. static _kernel_oserror *xFiles_FileInfo(xFiles_info *pInfo, _kernel_swi_regs *regs)
  222. {
  223.    _kernel_oserror *err;
  224.    xFiles_dirEntry dirEnt;
  225.    unsigned hashOffset;
  226.  
  227.    if (err = xFiles_parsePath(pInfo, (const char *) regs->r[1], NULL, &hashOffset, NULL, NULL, &dirEnt, FALSE), err)
  228.       return err;
  229.  
  230.    if (hashOffset == 0)
  231.       regs->r[0] = 0;
  232.    else
  233.    {
  234.       regs->r[0] = (dirEnt.attr & xFiles_isDir) ? 2 : 1;
  235.       regs->r[2] = dirEnt.load;
  236.       regs->r[3] = dirEnt.exec;
  237.       regs->r[4] = dirEnt.size;
  238.       regs->r[5] = dirEnt.attr & 0xFF;
  239.    }   
  240.  
  241.    return NULL;
  242. }
  243.  
  244. static _kernel_oserror *xFiles_UpdateInfo(xFiles_info *pInfo, _kernel_swi_regs *regs)
  245. {
  246.    _kernel_oserror *err;
  247.    xFiles_dirEntry dirEnt;
  248.    unsigned hashOffset;
  249.    unsigned entryOffset;
  250.    unsigned parent;     
  251.  
  252.    const char *objName = (const char *) regs->r[1];
  253.  
  254.    if (*objName == '\0')  /* don't even bother trying with the root */
  255.       return NULL;
  256.  
  257.    if (err = xFiles_parsePath(pInfo, objName, &parent, &hashOffset, &entryOffset, NULL, &dirEnt, FALSE), err)
  258.       return err;
  259.  
  260.    if (hashOffset == 0)
  261.       return NULL;
  262.  
  263.    dirEnt.load = regs->r[2];
  264.    dirEnt.exec = regs->r[3];
  265.    dirEnt.attr = (dirEnt.attr & 0xFFFFFF00) | (regs->r[5] & 0xFF);
  266.  
  267.    if (err = xFiles_writeChunk(pInfo, &dirEnt, parent, entryOffset, sizeof(dirEnt)), err)
  268.       return err;
  269.  
  270.    return NULL;
  271. }
  272.  
  273. static _kernel_oserror *xFiles_NewImage(_kernel_swi_regs *regs)
  274. {
  275.    xFiles_info *pInfo;
  276.    _kernel_oserror *err;
  277.  
  278.    if (pInfo = malloc(sizeof(xFiles_info)), !pInfo)
  279.       return &xFiles_NoMemory;
  280.  
  281.    xFiles_InitItem(&pInfo->li);
  282.    xFiles_InitList(&pInfo->openList);
  283.  
  284.    pInfo->fileHandle = regs->r[1];
  285.  
  286.    /* Should this perhaps take some notice of the sage advice which appears
  287.     * on page 4-46 of the PRM?
  288.     */
  289.  
  290.    if (err = xFiles_OpenImage(pInfo), err)
  291.       return err;
  292.  
  293.    regs->r[1] = (int) pInfo;
  294.    return NULL;
  295. }
  296.  
  297. static _kernel_oserror *xFiles_Delete(xFiles_info *pInfo, const char *objName)
  298. {
  299.    _kernel_oserror *err;
  300.    xFiles_fileInfo *pFile;
  301.    xFiles_dirHash  dirHash;
  302.    xFiles_dirEntry dirEnt;
  303.    unsigned hashOffset;
  304.    unsigned entryOffset;
  305.    unsigned parent;
  306.  
  307.    /*TRACE("Delete %s\n", objName);*/
  308.  
  309.    if (*objName == '\0')  /* don't even bother trying with the root */
  310.       return NULL;
  311.  
  312.    if (err = xFiles_parsePath(pInfo, objName, &parent, &hashOffset, &entryOffset, &dirHash, &dirEnt, FALSE), err)
  313.       return err;
  314.  
  315.    /* Don't delete an open file */
  316.  
  317.    if (pFile = xFiles_FindOpenFile(pInfo, dirHash.node), pFile)
  318.       return &xFiles_IsOpen;
  319.  
  320.    if (hashOffset == 0)
  321.       return NULL;
  322.  
  323.    if (dirEnt.attr & xFiles_locked)
  324.       return &xFiles_Locked;
  325.  
  326.    if (dirEnt.attr & xFiles_isDir)
  327.    {
  328.       xFiles_dirHeader dirHdr;
  329.       
  330.       if (err = xFiles_getDirHeader(pInfo, dirHash.node, &dirHdr), err)
  331.          return err;
  332.  
  333.       if (dirHdr.used != 0)
  334.          return NULL; /* &xFiles_DirNotEmpty; */
  335.    }
  336.  
  337.    if (err = xFiles_deleteDirEntry(pInfo, parent, hashOffset), err)
  338.       return err;
  339.  
  340.    if (err = xFiles_freeChunk(pInfo, dirHash.node), err)
  341.       return err;
  342.  
  343.    return NULL;
  344.  
  345. }
  346.  
  347. static _kernel_oserror *xFiles_ObjectExists(xFiles_info *pInfo, const char *pName, BOOL *pExists)
  348. {
  349.    _kernel_oserror *err;
  350.    unsigned hashOffset;
  351.  
  352.    if (err = xFiles_parsePath(pInfo, pName, NULL, &hashOffset, NULL, NULL, NULL, FALSE), err)
  353.       return err;
  354.  
  355.    if (pExists) *pExists = (hashOffset != 0);
  356.  
  357.    return NULL;
  358. }
  359.  
  360. static _kernel_oserror *xFiles_CDir(xFiles_info *pInfo, _kernel_swi_regs *regs)
  361. {
  362.    _kernel_oserror *err;
  363.    xFiles_dirEntry dirEnt, newDir;
  364.    xFiles_dirHash  dirHash, newHash;
  365.    const char *dirName = (const char *) regs->r[1];
  366.    unsigned hashOffset;
  367.    BOOL exists;
  368.  
  369.    /*TRACE("CDir %s\n", dirName);*/   
  370.  
  371.    if (err = xFiles_ObjectExists(pInfo, dirName, &exists), err)
  372.       return err;
  373.  
  374.    if (exists)
  375.       return NULL;
  376.  
  377.    if (err = xFiles_parsePath(pInfo, dirName, NULL, &hashOffset, NULL, &dirHash, &dirEnt, TRUE), err)
  378.       return err;
  379.  
  380.    if (hashOffset == 0)
  381.       return &xFiles_NotFound;
  382.  
  383.    if (err = xFiles_cDir(pInfo, dirHash.node, &newHash.node), err)
  384.       return err;
  385.  
  386.    newDir.load = regs->r[2];
  387.    newDir.exec = regs->r[3];
  388.    newDir.size = 0;
  389.    newDir.attr = xFiles_meRead | xFiles_meWrite | xFiles_isDir;
  390.  
  391.    if (err = xFiles_createDirEntry(pInfo, dirHash.node, &newHash, &newDir, xFiles_Leaf(dirName)), err)
  392.       return err;
  393.  
  394.    return NULL;
  395. }
  396.  
  397. static _kernel_oserror *xFiles_Create(xFiles_info *pInfo, _kernel_swi_regs *regs, unsigned *pCnk)
  398. {
  399.    _kernel_oserror *err;
  400.    const char *fileName = (const char *) regs->r[1];
  401.    xFiles_dirEntry dirEnt, newFile;
  402.    xFiles_dirHash dirHash, newHash;
  403.    unsigned hashOffset, entryOffset, parent;
  404.  
  405.    /*TRACE("Create %s\n", fileName);*/
  406.  
  407. #if 0
  408.    if (err = xFiles_Delete(pInfo, fileName), err)
  409.       return err;
  410. #else
  411.    if (err = xFiles_parsePath(pInfo, fileName, &parent, &hashOffset, &entryOffset, &dirHash, &dirEnt, FALSE), err)
  412.       return err;
  413.  
  414.    if (hashOffset != 0)  /* File already exists */
  415.    {
  416.       if (err = xFiles_setChunkSize(pInfo, dirHash.node, regs->r[5] - regs->r[4]), err)
  417.          return err;
  418.          
  419.       dirEnt.load = regs->r[2];
  420.       dirEnt.exec = regs->r[3];
  421.       dirEnt.size = regs->r[5] - regs->r[4];
  422.  
  423.       if (err = xFiles_writeChunk(pInfo, &dirEnt, parent, entryOffset, sizeof(dirEnt)), err)
  424.          return err;
  425.  
  426.       if (pCnk) *pCnk = dirHash.node;
  427.       return NULL;
  428.    }
  429. #endif   
  430.  
  431.    if (err = xFiles_parsePath(pInfo, fileName, NULL, &hashOffset, NULL, &dirHash, &dirEnt, TRUE), err)
  432.       return err;
  433.  
  434.    if (hashOffset == 0)
  435.       return &xFiles_NotFound;
  436.  
  437.    if (err = xFiles_newChunk(pInfo, &newHash.node), err)
  438.       return err;
  439.  
  440.    if (err = xFiles_setChunkSize(pInfo, newHash.node, regs->r[5] - regs->r[4]), err)
  441.       return err;
  442.  
  443.    newFile.load = regs->r[2];
  444.    newFile.exec = regs->r[3];
  445.    newFile.size = regs->r[5] - regs->r[4];
  446.    newFile.attr = xFiles_meRead | xFiles_meWrite;
  447.  
  448.    if (err = xFiles_createDirEntry(pInfo, dirHash.node, &newHash, &newFile, xFiles_Leaf(fileName)), err)
  449.       return err;
  450.  
  451.    if (pCnk) *pCnk = newHash.node;
  452.  
  453.    return NULL;
  454. }
  455.  
  456. static _kernel_oserror *xFiles_Save(xFiles_info *pInfo, _kernel_swi_regs *regs)
  457. {
  458.    _kernel_oserror *err;
  459.    unsigned newChunk;
  460.  
  461.    if (err = xFiles_Create(pInfo, regs, &newChunk), err)
  462.       return err;
  463.  
  464.    return xFiles_writeChunk(pInfo, (void *) regs->r[4], newChunk, 0, regs->r[5] - regs->r[4]);
  465. }
  466.  
  467. static _kernel_oserror *xFiles_FindFile(xFiles_info *pInfo, const char *fileName,
  468.                                         xFiles_dirHash *pDirHash, xFiles_dirEntry *pDirEnt,
  469.                                         unsigned *pParent)
  470. {
  471.    _kernel_oserror *err;
  472.  
  473.    if (err = xFiles_FindObject(pInfo, fileName, pDirHash, pDirEnt, pParent), err)
  474.       return err;
  475.  
  476.    if ((pDirEnt->attr & xFiles_isDir) != 0)
  477.       return &xFiles_NotAFile;
  478.  
  479.    return NULL;
  480. }
  481.  
  482. /* Locate an open file's directory information by looking it up
  483.  * in it's parent directory.
  484.  */
  485.  
  486. static _kernel_oserror *xFiles_LocateOpenFile(xFiles_info *pInfo, xFiles_fileInfo *pFileInfo,
  487.                                               unsigned *pEntryOffset, xFiles_dirEntry *pDirEnt)
  488. {
  489.    _kernel_oserror *err;
  490.    unsigned hashOffset;
  491.    xFiles_dirHash dirHash;
  492.  
  493.    /* Might want to change this to return the hash too? */
  494.  
  495.    if (err = xFiles_dirLookupByNode(pInfo, pFileInfo->parentDir, pFileInfo->cnkNum,
  496.                               &hashOffset, pEntryOffset, &dirHash), err)
  497.       return err;
  498.  
  499.    if (hashOffset == 0)
  500.       return &xFiles_LostTrack;
  501.  
  502.    if (pDirEnt)
  503.    {
  504.       if (err = xFiles_readChunk(pInfo, (void *) pDirEnt, pFileInfo->parentDir,
  505.                                  dirHash.entryPos, sizeof(xFiles_dirEntry)), err)
  506.          return err;
  507.    }
  508.  
  509.    return NULL;   
  510. }
  511.  
  512. /*********************************************************************************/
  513. /*                                                                               */
  514. /*   Filing system functionality (at last)                                       */
  515. /*                                                                               */
  516. /*********************************************************************************/
  517.  
  518. _kernel_oserror *xFiles_Open(_kernel_swi_regs *regs)
  519. {
  520.    _kernel_oserror *err;
  521.    const char *fileName = (const char *) regs->r[1];
  522.    xFiles_info *pInfo = (xFiles_info *) regs->r[6];
  523.    xFiles_fileInfo *pFileInfo;
  524.    xFiles_dirEntry dirEnt;
  525.    xFiles_dirHash  dirHash;
  526.  
  527.    if (pFileInfo = malloc(sizeof(xFiles_fileInfo)), !pFileInfo)
  528.       return &xFiles_NoMemory;
  529.  
  530.    xFiles_InitItem(&pFileInfo->li);
  531.  
  532.    pFileInfo->fileSwitchHandle = regs->r[3];
  533.    pFileInfo->pOwner = pInfo;
  534.  
  535.    /*TRACE("Open(%s)\n", leafName);*/
  536.  
  537.    if (err = xFiles_FindFile(pInfo, fileName, &dirHash, &dirEnt, &pFileInfo->parentDir), err)
  538.       goto failed;
  539.  
  540.    pFileInfo->cnkNum   = dirHash.node;
  541.    pFileInfo->fileSize = dirEnt.size;
  542.  
  543.    regs->r[0] = dirEnt.attr << 30;
  544.    regs->r[1] = (int) pFileInfo;
  545.    regs->r[2] = pInfo->fileHeader.allocationUnit;
  546.    regs->r[3] = dirEnt.size;
  547.    regs->r[4] = (dirEnt.size + 1023) & ~1023;
  548.  
  549.    if (err = xFiles_Commit(pInfo), err)
  550.       return err;
  551.  
  552.    /* Link it in to it's owner */
  553.  
  554.    xFiles_AddAtHead(&pInfo->openList, &pFileInfo->li);      
  555.  
  556.    return NULL;
  557.  
  558. failed:
  559.    free(pFileInfo);
  560.    regs->r[1] = 0;
  561.    return err;
  562. }
  563.  
  564. _kernel_oserror *xFiles_GetBytes(_kernel_swi_regs *regs)
  565. {
  566.    xFiles_fileInfo *pFileInfo = (xFiles_fileInfo *) regs->r[1];
  567.    xFiles_info *pInfo = pFileInfo->pOwner;
  568.    unsigned pos  = regs->r[4];
  569.    unsigned size = regs->r[3];
  570.  
  571.    if (pos + size > pFileInfo->fileSize)
  572.       size = pFileInfo->fileSize - pos;
  573.  
  574.    /*TRACE("GetBytes() %08x, %08x, %08x\n", regs->r[2], regs->r[3], regs->r[4]);*/
  575.  
  576.    return xFiles_readChunk(pInfo, (void *) regs->r[2], pFileInfo->cnkNum, pos, size);
  577. }
  578.  
  579. _kernel_oserror *xFiles_PutBytes(_kernel_swi_regs *regs)
  580. {
  581.    _kernel_oserror *err;
  582.    xFiles_fileInfo *pFileInfo = (xFiles_fileInfo *) regs->r[1];
  583.    xFiles_info *pInfo = pFileInfo->pOwner;
  584.    unsigned pos  = regs->r[4];
  585.    unsigned size = regs->r[3];
  586.  
  587.    /*TRACE("PutBytes() %08x, %08x, %08x\n", regs->r[2], regs->r[3], regs->r[4]);
  588.    TRACE("pFileInfo->cnkNum = %08x\n", pFileInfo->cnkNum);*/
  589.  
  590.    if (err = xFiles_writeChunk(pInfo, (void *) regs->r[2], pFileInfo->cnkNum, pos, size), err)
  591.       return err;
  592.  
  593.    return xFiles_Commit(pInfo);
  594. }
  595.  
  596. _kernel_oserror *xFiles_Args(_kernel_swi_regs *regs)
  597. {
  598.    _kernel_oserror *err;
  599.    unsigned entryOffset;
  600.    xFiles_fileInfo *pFileInfo = (xFiles_fileInfo *) regs->r[1];
  601.    xFiles_info *pInfo = pFileInfo->pOwner;
  602.    xFiles_dirEntry dirEnt;
  603.    BOOL update = FALSE;
  604.  
  605.    if (err = xFiles_LocateOpenFile(pInfo, pFileInfo, &entryOffset, &dirEnt), err)
  606.       return err;
  607.  
  608.    switch (regs->r[0])
  609.    {
  610.       case 7:  /* ensure file size */
  611.          /*TRACE("Ensure file is >= %08x (currently %08x)\n", regs->r[2], dirEnt.size);*/
  612.          if (regs->r[2] <= dirEnt.size)
  613.             break;
  614.  
  615.       case 3:  /* write file extent */
  616.          if (err = xFiles_setChunkSize(pInfo, pFileInfo->cnkNum, regs->r[2]), err)
  617.             return err;
  618.          dirEnt.size = regs->r[2];
  619.          pFileInfo->fileSize = regs->r[2];
  620.          update = TRUE;
  621.          break;
  622.  
  623.       case 4:
  624.          regs->r[2] = dirEnt.size;
  625.          break;
  626.  
  627.       case 9:
  628.          regs->r[2] = dirEnt.load;
  629.          regs->r[3] = dirEnt.exec;
  630.          break;
  631.  
  632.       case 6:
  633.       case 8:  /* write zeros */
  634.       case 10:
  635.          break;
  636.  
  637.       default:
  638.          TRACE("Args(%d) called\n", regs->r[0]);
  639.          return &xFiles_NotImplemented;
  640.    }
  641.  
  642.    if (update)
  643.    {
  644.       if (err = xFiles_writeChunk(pInfo, &dirEnt, pFileInfo->parentDir,
  645.                                   entryOffset, sizeof(dirEnt)), err)
  646.          return err;
  647.    }
  648.  
  649.    return xFiles_Commit(pInfo);
  650. }
  651.  
  652. _kernel_oserror *xFiles_Close(_kernel_swi_regs *regs)
  653. {
  654.    _kernel_oserror *err;
  655.    unsigned entryOffset;
  656.    xFiles_fileInfo *pFileInfo = (xFiles_fileInfo *) regs->r[1];
  657.    xFiles_info *pInfo = pFileInfo->pOwner;
  658.    xFiles_dirEntry dirEnt;
  659.  
  660.    /*TRACE("Close()\n");*/
  661.  
  662.    if (err = xFiles_LocateOpenFile(pInfo, pFileInfo, &entryOffset, &dirEnt), err)
  663.       return err;
  664.  
  665.    if (regs->r[2] != 0) dirEnt.load = regs->r[2];
  666.    if (regs->r[3] != 0) dirEnt.exec = regs->r[3];
  667.  
  668.    if (regs->r[2] != 0 || regs->r[3] != 0)
  669.    {
  670.       if (err = xFiles_writeChunk(pInfo, &dirEnt, pFileInfo->parentDir,
  671.                                   entryOffset, sizeof(dirEnt)), err)
  672.          return err;
  673.    }
  674.  
  675.    if (err = xFiles_Commit(pInfo), err)
  676.       return err;
  677.  
  678.    /* Can't error now, so unlink it and get rid of it */
  679.  
  680.    xFiles_Remove(&pInfo->openList, &pFileInfo->li);
  681.    free(pFileInfo);
  682.  
  683.    return NULL;
  684. }
  685.  
  686. _kernel_oserror *xFiles_File(_kernel_swi_regs *regs)
  687. {
  688.    _kernel_oserror *err;
  689.    xFiles_info *pInfo = (xFiles_info *) regs->r[6];
  690.  
  691.    switch (regs->r[0])
  692.    {
  693.       case 0:
  694.          if (err = xFiles_Save(pInfo, regs), err) return err;
  695.          break;
  696.  
  697.       case 1:
  698.          if (err = xFiles_UpdateInfo(pInfo, regs), err) return err;
  699.          break;
  700.  
  701.       case 5:
  702.          if (err = xFiles_FileInfo(pInfo, regs), err) return err;
  703.          break;
  704.  
  705.       case 6:
  706.          if (err = xFiles_Delete(pInfo, (const char *) regs->r[1]), err) return err;
  707.          break;
  708.  
  709.       case 7:
  710.          if (err = xFiles_Create(pInfo, regs, NULL), err) return err;
  711.          break;
  712.  
  713.       case 8:
  714.          if (err = xFiles_CDir(pInfo, regs), err) return err;
  715.          break;
  716.          
  717.       default:
  718.          TRACE("File(%d) called\n", regs->r[0]);
  719.          return &xFiles_NotImplemented;
  720.    }
  721.  
  722.    return xFiles_Commit(pInfo);
  723. }
  724.  
  725. _kernel_oserror *xFiles_Func(_kernel_swi_regs *regs)
  726. {
  727.    xFiles_info *pInfo = (xFiles_info *) regs->r[6];
  728.    _kernel_oserror *err;
  729.  
  730.    /*TRACE("Func(%d) called\n", regs->r[0]);*/
  731.  
  732.    switch (regs->r[0])
  733.    {
  734.       case 8: /* rename object */
  735.          if (err = xFiles_Rename(pInfo, (const char *) regs->r[1], (const char *) regs->r[2]), err)
  736.             return err;
  737.          regs->r[1] = 0;
  738.          return xFiles_Commit(pInfo);
  739.  
  740.       case 14: /* read directory entries */
  741.       case 15:
  742.          return xFiles_ReadDirEntries(pInfo, (const char *) regs->r[1],
  743.                                       (void *) regs->r[2], ®s->r[3], ®s->r[4], regs->r[5],
  744.                                       regs->r[0] == 15);
  745.  
  746.       case 21: /* new image notification */
  747.          return xFiles_NewImage(regs);
  748.  
  749.       case 22:
  750.          return xFiles_CloseImage((xFiles_info *) regs->r[1]);
  751.  
  752.       case 27: /* return boot option */
  753.          regs->r[2] = 0;
  754.          return NULL;
  755.  
  756.       default:
  757.          TRACE("Func(%d) called\n", regs->r[0]);
  758.          return &xFiles_NotImplemented;
  759.    }
  760.  
  761.    return NULL;
  762. }
  763.  
  764.